home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PsL Monthly 1993 December
/
PSL Monthly Shareware CD-ROM (December 1993).iso
/
prgmming
/
dos
/
c
/
structs.c
< prev
next >
Wrap
Text File
|
1991-01-25
|
14KB
|
429 lines
/*************************************************************************
This program is a demonstration of using arrays of structures
for such tasks as screen painting, field definition, and data file
searching.
This program is submitted as public domain. It's basic concept is
to communicate some uses of data structures and re-useable coding.
This program (along with other BTree and similiar structure based
programs) is the result of a C programming part II class I taught
at a local university. Several of my students have stated how much
easier project developement was with routines similiar to these.
Mario Giannini
Compuserve #76276,1576
January 25, 1991
*************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <io.h>
#include <fcntl.h>
#include <sys\types.h>
#include <sys\stat.h>
#include <dos.h>
#include <malloc.h> /* alloc.h for TurboC */
#include <string.h>
/*************************************************************************/
/* Key macros to make life easier */
#define ESC 0x1B
#define F10 0x4400
#define CURUP 0x4800
#define CURDN 0x5000
#define BACKSPACE 0x0008
#define ENTER 0x000D
#define TextColor 7
#define DataColor 0xF
#define INDEXFLD 0x0001
/* Here are our basic data structure definitions */
typedef struct {
int H, V, Len, Option, Type, FieldNum;
char *Text, *Data;
} FIELDS;
typedef struct {
int Handle, RecSize;
FIELDS *EditFields;
char *Filename, *RecSpace;
long Recpos;
} RECORD;
/*************************************************************************/
/* Here are data declarations, it should be noted that the record types
** can be changed here, and upon re-compile all of the code should
** still work as always, interpreting the structures themselves
**/
FIELDS PersonFields[]={
0, 0, 10, 0, 0, 0, "First", NULL,
25, 0, 10, 0, INDEXFLD, 0, "Last", NULL,
0, 2, 35, 0, 0, 0, "Company", NULL,
0, 3, 35, 0, 0, 0, "Comment", NULL,
0, 0, 0, 0, 0, 0, NULL, NULL}; /* NULL for Text is terminator */
RECORD Person={0, 0, PersonFields, "PERSON.DAT", NULL, 0L};
FIELDS TransFields[]={
0, 0, 8, 0, 0, 0, "Date", NULL,
25, 0, 10, 0, 0, 0, "Amount", NULL,
0, 0, 0, 0, 0, 0, NULL, NULL}; /* NULL for Text is terminator */
RECORD Transaction={0, 0, TransFields, "TRANS.DAT", NULL,0L};
/*************************************************************************/
/* Sort of a 'main menu' of tables we can edit */
RECORD *AllRecords[]={&Person, &Transaction, NULL};
/*************************************************************************/
/**** Function prototypes ***/
void main(void);
void AddItem(RECORD *Record);
void EditItem(RECORD *Record);
int EditRecord(RECORD *Record);
void ShowScreen(RECORD *Record);
void ShowData(RECORD *Record);
void Cls(int Color);
void Locate(int H,int V);
void PrintStr(char *Str,int Color);
void Message(char *Str,int Wait);
int MyGets(char *Dest,int Len);
int GetKey(void);
int AppendRecord(RECORD *Record);
int LocateRecord(RECORD *Rec);
int ReadRecord(RECORD *Record);
int WriteRecord(RECORD *Record);
void BlankRecord(RECORD *Record);
int OpenFile(RECORD *Record);
void CloseFile(RECORD *Record);
/*************************************************************************/
/*** Start of code section ***/
/*** ***/
/*************************************************************************/
void main(void)
{
int i, NumOfRecs, Ch=0, Ch2;
while(Ch!=ESC)
{
Cls(7);
for(NumOfRecs=0;AllRecords[NumOfRecs];NumOfRecs++)
printf("%d: %s\n", NumOfRecs+1, AllRecords[NumOfRecs]->Filename);
printf("\nESC to quit.\n\nPlease press a key..");
do {
Ch=GetKey();
} while(Ch!=ESC && (Ch<'0'||Ch-'1'>NumOfRecs));
if(Ch==ESC)
continue;
Cls(7);
printf("You Selected %s\n\n", AllRecords[Ch-'1']->Filename);
printf("A) Add\nE) Edit\n\nESC for previous menu\n\nMake selection:");
do {
Ch2=getch();
Ch2=toupper(Ch2);
} while( Ch2!=ESC && Ch2!='A' && Ch2!='E') ;
/*
** Note how the AllRecord array is used to process table based on user
** selection.
*/
if(Ch2=='A')
AddItem(AllRecords[Ch-'1']);
if(Ch2=='E')
EditItem(AllRecords[Ch-'1']);
}
}
/*************************************************************************/
/*** Higher-level functions ***/
/*** ***/
/*************************************************************************/
void AddItem(RECORD *Record)
{
Cls(7);
OpenFile(Record);
ShowScreen(Record);
BlankRecord(Record);
Message("Press ESC to Abort, F10 to Add",0);
if(EditRecord(Record)==F10)
AppendRecord(Record);
CloseFile(Record);
Message("", 0);
}
/*************************************************************************/
void EditItem(RECORD *Record)
{
Cls(7);
OpenFile(Record);
ShowScreen(Record);
BlankRecord(Record);
Message("Press ESC to Abort, F10 to start search",0);
if(EditRecord(Record)==F10)
{
if(LocateRecord(Record))
{
Message("Press ESC to abort, F10 to save updates", 0);
ReadRecord(Record);
ShowData(Record);
if(EditRecord(Record)==F10)
WriteRecord(Record);
}
else
Message("Criteria not found. Press any key to continue",1);
}
CloseFile(Record);
Message("",0);
}
/*************************************************************************/
/*** ScreenI/O section follows ***/
/*** ***/
/*************************************************************************/
int EditRecord(RECORD *Record) /* Edits a Record */
{
int i=0, Ch=0, LastEntry=0;
/*
** Note how this founction interprets whatever structures are passed
** to it at run-time. Not much is hard-coded.
*/
for(LastEntry=0;Record->EditFields[LastEntry].Text;LastEntry++)
;
while(Ch!=ESC && Ch!=F10)
{
Locate(Record->EditFields[i].H+strlen(Record->EditFields[i].Text)+1,
Record->EditFields[i].V);
Ch=MyGets(Record->EditFields[i].Data, Record->EditFields[i].Len);
if( (Ch==ENTER||Ch==CURDN) && ++i>=LastEntry)
i=0;
if(Ch==CURUP && --i<0)
i=LastEntry-1;
}
return(Ch);
}
/****************************************************************/
void ShowScreen(RECORD *Record) /* Show Screen layout Data */
{
int i=0;
for(i=0;Record->EditFields[i].Text;i++)
{
Locate(Record->EditFields[i].H, Record->EditFields[i].V);
PrintStr(Record->EditFields[i].Text, TextColor);
}
}
/****************************************************************/
void ShowData(RECORD *Record) /* Show Record Data */
{
int i=0;
for(i=0;Record->EditFields[i].Text;i++)
{
Locate(Record->EditFields[i].H+strlen(Record->EditFields[i].Text)+1,
Record->EditFields[i].V);
PrintStr(Record->EditFields[i].Data, DataColor);
}
}
/****************************************************************/
void Cls(int Color) /* Clears the screen to any color */
{
union REGS Regin;
Regin.x.ax=0x0600;
Regin.h.bh=(char)Color;
Regin.x.cx=0;
Regin.x.dx=0x1950;
int86(0x10, &Regin, &Regin);
Locate(0,0);
}
/****************************************************************/
void Locate(int H, int V) /* Locate cursor at an Horiz, Vert coordinate */
{
union REGS Regin;
Regin.h.ah=2;
Regin.h.bh=0;
Regin.h.dh=(char)V;
Regin.h.dl=(char)H;
int86(0x10, &Regin, &Regin);
}
/****************************************************************/
void PrintStr(char *Str, int Color) /* Generic color print string routine */
{
union REGS Regin;
Regin.h.ah=9;
Regin.h.al=*Str;
Regin.x.cx=strlen(Str);
Regin.h.bl=(char)Color;
Regin.h.bh